home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / windownt / embh32.zip / EMBH.C next >
C/C++ Source or Header  |  1993-09-16  |  25KB  |  726 lines

  1. /****************************************************************************
  2. *                                                                           *
  3. *              EMBH: Embedded windows for Windows Help projects.            *
  4. *                             Windows NT Version                            *
  5. *                          2/18/93  by  Mark Gamber                         *
  6. *                                                                           *
  7. ****************************************************************************/
  8.  
  9. #include "windows.h"
  10. #include "mmsystem.h"
  11. #include "embh.h"
  12.  
  13.  
  14. HANDLE hInst;
  15. int WinDoc;
  16.  
  17. char *BULLET = "BULLET";                          //  Class names for windows
  18. char *ARROW = "ARROW";
  19. char *MODEM = "MODEM";
  20. char *POINTER = "POINTER";
  21.  
  22. char *WSIZE = "SIZE";
  23. char *XSIZE = "XSIZE";
  24. char *YSIZE = "YSIZE";
  25. char *FILES = "FILES";
  26.  
  27. /****************************************************************************
  28. *                                                                           *
  29. *         LibMain() - Entry point to DLL. Registers windows classes.        *
  30. *                                                                           *
  31. ****************************************************************************/
  32.  
  33. BOOL WINAPI DLLEntryPoint( HANDLE hDll, DWORD dwReason, LPVOID lpReserved )
  34. {
  35.    WNDCLASS wc;
  36.  
  37.    hInst = hDll;
  38.  
  39.    wc.style = CS_GLOBALCLASS;
  40.    wc.lpfnWndProc = BulletWndProc;
  41.    wc.cbClsExtra = 0;
  42.    wc.cbWndExtra = BULLET_EXTRA_BYTES;
  43.    wc.hIcon = NULL;
  44.    wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  45.    wc.hbrBackground = GetStockObject( NULL_BRUSH );
  46.    wc.hInstance = hDll;
  47.    wc.lpszMenuName = NULL;
  48.    wc.lpszClassName = BULLET;
  49.  
  50.    RegisterClass( &wc );
  51.  
  52.    wc.style = CS_GLOBALCLASS;
  53.    wc.lpfnWndProc = ArrowWndProc;
  54.    wc.cbClsExtra = 0;
  55.    wc.cbWndExtra = ARROW_EXTRA_BYTES;
  56.    wc.hIcon = NULL;
  57.    wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  58.    wc.hbrBackground = GetStockObject( NULL_BRUSH );
  59.    wc.hInstance = hDll;
  60.    wc.lpszMenuName = NULL;
  61.    wc.lpszClassName = ARROW;
  62.  
  63.     RegisterClass( &wc );
  64.  
  65.    wc.style = CS_GLOBALCLASS;
  66.    wc.lpfnWndProc = ModemWndProc;
  67.    wc.cbClsExtra = 0;
  68.    wc.cbWndExtra = MODEM_EXTRA_BYTES;
  69.    wc.hIcon = NULL;
  70.    wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  71.    wc.hbrBackground = GetStockObject( NULL_BRUSH );
  72.    wc.hInstance = hDll;
  73.    wc.lpszMenuName = NULL;
  74.    wc.lpszClassName = MODEM;
  75.  
  76.     RegisterClass( &wc );
  77.  
  78.    wc.style = CS_GLOBALCLASS;
  79.    wc.lpfnWndProc = RightPointerWndProc;
  80.    wc.cbClsExtra = 0;
  81.    wc.cbWndExtra = RPOINTER_EXTRA_BYTES;
  82.    wc.hIcon = NULL;
  83.    wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  84.    wc.hbrBackground = GetStockObject( NULL_BRUSH );
  85.    wc.hInstance = hDll;
  86.    wc.lpszMenuName = NULL;
  87.    wc.lpszClassName = POINTER;
  88.  
  89.     RegisterClass( &wc );
  90.     
  91.    return( TRUE );
  92. }
  93.  
  94.  
  95.  
  96. /****************************************************************************
  97. *                                                                           *
  98. *                             Bullet window process                         *
  99. *                                                                           *
  100. ****************************************************************************/
  101.  
  102. LONG WINAPI BulletWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
  103. {
  104.    switch( msg )
  105.    {
  106.       case 0x706B:                     //  Custom message from Winhelp asking
  107.          ((LPPOINT)lParam)->x = 10;     //  for embedded window size. Fill in
  108.          ((LPPOINT)lParam)->y = 10;       //  Point structure tellng it 10x10
  109.          return( 1L );
  110.  
  111.       case WM_CREATE:
  112.       {
  113.          LPCREATESTRUCT lpCs = (LPCREATESTRUCT)lParam;
  114.          LPEWDATA lpEw;
  115.          WORD i;
  116.  
  117.          lpEw = (LPEWDATA)lpCs->lpCreateParams;    //  Get EWDATA from Struct
  118.          i = 0;
  119.  
  120.          if( lstrlen( lpEw->szAuthorData ) )       //  If there's a parameter
  121.          {
  122.             if( lpEw->szAuthorData[ 0 ] == 'F' )          //  Forward cycling
  123.                SetWindowLong( hWnd, BULLET_CYCLING, 1 );
  124.             else
  125.                if( lpEw->szAuthorData[ 0 ] == 'B' )   //  Or backward cycling
  126.                   SetWindowLong( hWnd, BULLET_CYCLING, 2 );
  127.                else
  128.                   SetWindowLong( hWnd, BULLET_CYCLING, 0 ); //  Or no cycling
  129.  
  130.             if( lpEw->szAuthorData[ 1 ] == '1' )    //  Determine what colors
  131.                i |= 1;                                  //  to use by looking
  132.             if( lpEw->szAuthorData[ 2 ] == '1' )      //  at next three chars
  133.                i |= 2;
  134.             if( lpEw->szAuthorData[ 3 ] == '1' )
  135.                i |= 4;
  136.  
  137.          }
  138.          SetWindowLong( hWnd, BULLET_COLOR, i );     //  Save color specifier
  139.          SetWindowLong( hWnd, BULLET_BRIGHT, 255 ); //  Save brightness value
  140.  
  141.          if( GetWindowLong( hWnd, BULLET_CYCLING ) )     //  If cycling is on
  142.             SetTimer( hWnd, 1, 100, NULL );          //  Start a system timer
  143.  
  144.          break;
  145.       }
  146.  
  147.       case WM_TIMER:                            //  Called if cycling enabled
  148.       {
  149.          WORD i, r, g, b;
  150.          DWORD dwColor;
  151.          HDC hDC;
  152.          HBRUSH hBrush;
  153.  
  154.          i = GetWindowLong( hWnd, BULLET_COLOR );  //  Get current color spec
  155.          r = g = b = 0;
  156.          if( i & 1 )
  157.             r = GetWindowLong( hWnd, BULLET_BRIGHT );  
  158.          if( i & 2 )                      
  159.             g = GetWindowLong( hWnd, BULLET_BRIGHT );
  160.          if( i & 4 )
  161.             b = GetWindowLong( hWnd, BULLET_BRIGHT );
  162.                                                //  Create a brush using color
  163.          hBrush = CreateSolidBrush( RGB( r, g, b ) );
  164.          hDC = GetDC( hWnd );
  165.          SelectObject( hDC, GetStockObject( BLACK_PEN ) );
  166.          SelectObject( hDC, hBrush );
  167.  
  168.          Ellipse( hDC, 0, 0, 10, 10 );                    //  Draw the bullet
  169.  
  170.          ReleaseDC( hWnd, hDC );
  171.          DeleteObject( hBrush );
  172.  
  173.          if( GetWindowLong( hWnd, BULLET_CYCLING ) == 1 )   //  If forward...
  174.          {
  175.             i = GetWindowLong( hWnd, BULLET_BRIGHT );      //  Get lum. value
  176.             if( i == 15 )                        //  If already at the bottom
  177.                i = 255;                               //  Put back at the top
  178.             else
  179.                i -= 16;                           //  Otherwise, knock off 16
  180.          }
  181.          else
  182.          {
  183.             i = GetWindowLong( hWnd, BULLET_BRIGHT );     //  If backwards...
  184.             if( i == 255 )                          //  If already at the top
  185.                i = 0;                                      //  Plug in a zero
  186.             else
  187.                i += 16;                                 //  Otherwise, add 16
  188.          }
  189.  
  190.          SetWindowLong( hWnd, BULLET_BRIGHT, i );          //  Save new value
  191.          break;
  192.       }
  193.  
  194.       case WM_PAINT:             //  Important mostly for non-cycling windows
  195.       {
  196.          PAINTSTRUCT Ps;
  197.          HDC hDC;
  198.          HBRUSH hBrush;
  199.          WORD i, r, g, b;
  200.  
  201.          hDC = BeginPaint( hWnd, &Ps );
  202.          i = GetWindowLong( hWnd, BULLET_COLOR );     //  Get color specifier
  203.  
  204.          r = g = b = 0;
  205.  
  206.          if( i & 1 )                    //  If color bit is set, turn full on
  207.             r = 255;
  208.          if( i & 2 )
  209.             g = 255;
  210.          if( i & 4 )
  211.             b = 255;
  212.                                           //  Make a brush from current color
  213.          hBrush = CreateSolidBrush( RGB( r, g, b ) );
  214.          SelectObject( hDC, GetStockObject( BLACK_PEN ) );
  215.          SelectObject( hDC, hBrush );
  216.          Ellipse( hDC, 0, 0, 10, 10 );               //  Draw bullet and exit
  217.  
  218.          EndPaint( hWnd, &Ps );
  219.          DeleteObject( hBrush );
  220.          return( TRUE );
  221.       }
  222.  
  223.       case WM_DESTROY:
  224.          if( GetWindowLong( hWnd, BULLET_CYCLING ) )
  225.             KillTimer( hWnd, 1 );            //  before allowing window to go
  226.          break;
  227.  
  228.       default:
  229.          return( DefWindowProc( hWnd, msg, wParam, lParam ) );
  230.    }
  231.    return( FALSE );
  232. }
  233.  
  234.  
  235. /****************************************************************************
  236. *                                                                           *
  237. *                ARROW window proc. Basically same as BULLET                *
  238. *                                                                           *
  239. ****************************************************************************/
  240.  
  241. LONG WINAPI ArrowWndProc( HWND hWnd, UINT msg, UINT wParam, LONG lParam )
  242. {
  243.    switch( msg )
  244.    {
  245.       case 0x706B:                      //  Size request message from Winhelp
  246.          ((LPPOINT)lParam)->x = 21;
  247.          ((LPPOINT)lParam)->y = 11;                     //  This one is 21x11
  248.          return( 1L );
  249.  
  250.       case WM_CREATE:
  251.       {
  252.          LPCREATESTRUCT lpCs = (LPCREATESTRUCT)lParam;
  253.          LPEWDATA lpEw;
  254.          WORD i;
  255.  
  256.          lpEw = (LPEWDATA)lpCs->lpCreateParams;
  257.          i = 0;
  258.  
  259.          if( lstrlen( lpEw->szAuthorData ) )
  260.          {
  261.             if( lpEw->szAuthorData[ 0 ] == 'F' )  //  Pick apart color values
  262.                SetWindowLong( hWnd, ARROW_CYCLING, 1 );
  263.             else
  264.                if( lpEw->szAuthorData[ 0 ] == 'B' )
  265.                   SetWindowLong( hWnd, ARROW_CYCLING, 2 );
  266.                else
  267.                   SetWindowLong( hWnd, ARROW_CYCLING, 0 );
  268.  
  269.             if( lpEw->szAuthorData[ 1 ] == '1' )
  270.                i |= 1;
  271.             if( lpEw->szAuthorData[ 2 ] == '1' )
  272.                i |= 2;
  273.             if( lpEw->szAuthorData[ 3 ] == '1' )
  274.                i |= 4;
  275.          }
  276.  
  277.          SetWindowLong( hWnd, ARROW_COLOR, i );
  278.          SetWindowLong( hWnd, ARROW_BRIGHT, 15 );
  279.  
  280.          if( GetWindowLong( hWnd, ARROW_CYCLING ) )    //  If cycling enabled
  281.             SetTimer( hWnd, 1, 100, NULL );                //  Obtain a timer
  282.  
  283.          break;
  284.       }
  285.  
  286.       case WM_TIMER:
  287.       {
  288.          WORD i, r, g, b;
  289.          DWORD dwColor;
  290.          HDC hDC;
  291.          HBRUSH hBrush;
  292.  
  293.          i = GetWindowLong( hWnd, ARROW_COLOR );          //  Get color spec.
  294.  
  295.          r = g = b = 0;
  296.          if( i & 1 )
  297.             r = GetWindowLong( hWnd, ARROW_BRIGHT ) * 16;    //  I screwed up and forgot
  298.          if( i & 2 )                            //  to be consistant, so this
  299.             g = GetWindowLong( hWnd, ARROW_BRIGHT ) * 16;   //  proc takes the luminence
  300.          if( i & 4 )                          //  from 1 to 16 and multiplies
  301.             b = GetWindowLong( hWnd, ARROW_BRIGHT ) * 16;   //  by 16 for real lum value
  302.  
  303.          hDC = GetDC( hWnd );
  304.  
  305.          hBrush = CreateSolidBrush( RGB( r, g, b ) );
  306.          SelectObject( hDC, GetStockObject( BLACK_PEN ) );
  307.          SelectObject( hDC, hBrush );
  308.          DrawArrow( hDC );                        //  Draw the arrow  (below)
  309.  
  310.          ReleaseDC( hWnd, hDC );
  311.          DeleteObject( hBrush );
  312.  
  313.          i = GetWindowLong( hWnd, ARROW_BRIGHT );
  314.          if( GetWindowWord( hWnd, ARROW_CYCLING ) == 1 )            //  If moving forward
  315.          {
  316.             if( i == 0 )                 //  Subtract one, wrapping if needed
  317.                i = 15;
  318.             else
  319.                --i;
  320.          }
  321.          else
  322.          {
  323.             if( i == 15 )                     //  Backwards, add one and wrap
  324.                i = 0;
  325.             else
  326.                ++i;
  327.          }
  328.  
  329.          SetWindowLong( hWnd, ARROW_BRIGHT, i );     //  Save current lum value and exit
  330.          break;
  331.       }
  332.  
  333.       case WM_PAINT:                   //  Repaint, mostly for static windows
  334.       {
  335.          PAINTSTRUCT Ps;
  336.          HDC hDC;
  337.          HBRUSH hBrush;
  338.          WORD i, r, g, b;
  339.  
  340.          hDC = BeginPaint( hWnd, &Ps );
  341.          i = GetWindowLong( hWnd, ARROW_COLOR );
  342.  
  343.          r = g = b = 0;
  344.          if( i & 1 )                    //  If color is enabled, turn on full
  345.             r = 255;
  346.          if( i & 2 )
  347.             g = 255;
  348.          if( i & 4 )
  349.             b = 255;
  350.  
  351.          SelectObject( hDC, GetStockObject( BLACK_PEN ) );
  352.          hBrush = CreateSolidBrush( RGB( r, g, b ) );
  353.          SelectObject( hDC, hBrush );
  354.          DrawArrow( hDC );                        //  Draw the arrow and exit
  355.  
  356.          EndPaint( hWnd, &Ps );
  357.          DeleteObject( hBrush );
  358.          return( TRUE );
  359.       }
  360.  
  361.       case WM_DESTROY:
  362.          if( GetWindowWord( hWnd, ARROW_CYCLING ) )      //  Kill the timer before window
  363.             KillTimer( hWnd, 1 );
  364.          break;
  365.  
  366.       default:
  367.          return( DefWindowProc( hWnd, msg, wParam, lParam ) );
  368.    }
  369.    return( FALSE );
  370. }
  371.  
  372.  
  373.  
  374. void DrawArrow( HDC hDC )
  375. {
  376.    POINT Pt[ 10 ];
  377.  
  378.    Pt[ 0 ].x = 0;                //  Fill in array of points describing arrow
  379.    Pt[ 0 ].y = 3;
  380.    Pt[ 1 ].x = 14;
  381.    Pt[ 1 ].y = 3;
  382.    Pt[ 2 ].x = 14;
  383.    Pt[ 2 ].y = 0;
  384.    Pt[ 3 ].x = 15;                                         //  Big list, huh?
  385.    Pt[ 3 ].y = 0;
  386.    Pt[ 4 ].x = 20;
  387.    Pt[ 4 ].y = 5;
  388.    Pt[ 5 ].x = 15;
  389.    Pt[ 5 ].y = 10;
  390.    Pt[ 6 ].x = 14;
  391.    Pt[ 6 ].y = 10;
  392.    Pt[ 7 ].x = 14;
  393.    Pt[ 7 ].y = 7;
  394.    Pt[ 8 ].x = 0;                 //  Maybe not as bad as a paint program but
  395.    Pt[ 8 ].y = 7;
  396.    Pt[ 9 ].x = 0;                                 //  Still a pain in the ass
  397.    Pt[ 9 ].y = 3;
  398.  
  399.    Polygon( hDC, (LPPOINT)Pt, 10 );                  //  (whew)....draw shape
  400. }
  401.  
  402.  
  403. /****************************************************************************
  404. *                                                                           *
  405. *                  MODEM window proc. This one is *real* easy               *
  406. *                                                                           *
  407. ****************************************************************************/
  408.  
  409. LONG WINAPI ModemWndProc( HWND hWnd, UINT msg, UINT wParam, LONG lParam )
  410. {
  411.    switch( msg )
  412.    {
  413.       case 0x706B:                              //  Size request from Winhelp
  414.          ((LPPOINT)lParam)->x = 31;                        //  Modem is 31x11
  415.          ((LPPOINT)lParam)->y = 11;
  416.          return( 1L );
  417.  
  418.       case WM_CREATE:
  419.          SetWindowLong( hWnd, MODEM_BLINK, 0 );   //  Initialize blink status
  420.          SetTimer( hWnd, 1, 100, NULL );       //  Enable timer and we're off
  421.          break;
  422.  
  423.       case WM_TIMER:
  424.       {
  425.          HDC hDC;
  426.          HDC mDC;
  427.          HBITMAP hBmp;
  428.  
  429.          hDC = GetDC( hWnd );
  430.          mDC = CreateCompatibleDC( hDC );
  431.                                                  //  Load bitmap depending on
  432.          if( ! GetWindowLong( hWnd, MODEM_BLINK ) )          //  blink status
  433.             hBmp = LoadBitmap( hInst, MAKEINTRESOURCE( 100 ) );
  434.          else
  435.             hBmp = LoadBitmap( hInst, MAKEINTRESOURCE( 101 ) );
  436.  
  437.          SelectObject( mDC, hBmp );
  438.                                                            //  Draw the modem
  439.          BitBlt( hDC, 0, 0, 31, 11, mDC, 0, 0, SRCCOPY );
  440.  
  441.          DeleteDC( mDC );
  442.          DeleteObject( hBmp );
  443.          ReleaseDC( hWnd, hDC );
  444.  
  445.          if( GetWindowLong( hWnd, MODEM_BLINK ) )    //  Toggle blink setting
  446.             SetWindowLong( hWnd, MODEM_BLINK, 0 );
  447.          else
  448.             SetWindowLong( hWnd, MODEM_BLINK, 1 );    //  Told ya it was easy
  449.  
  450.          break;
  451.       }
  452.  
  453.       case WM_DESTROY:
  454.          KillTimer( hWnd, 1 );          //  Make timer die before window does
  455.          break;
  456.  
  457.       default:
  458.          return( DefWindowProc( hWnd, msg, wParam, lParam ) );
  459.    }
  460.    return( FALSE );
  461. }
  462.  
  463.  
  464. /****************************************************************************
  465. *                                                                           *
  466. *     Right pointer - Color is specified at creation and may be changed     *
  467. *                                                                           *
  468. ****************************************************************************/
  469.  
  470. LONG WINAPI RightPointerWndProc( HWND hWnd, UINT msg, UINT wParam, LONG lParam )
  471. {
  472.    switch( msg )
  473.    {
  474.       case 0x706B:
  475.          ((LPPOINT)lParam)->x = 11;
  476.          ((LPPOINT)lParam)->y = 11;
  477.          return( 1L );
  478.  
  479.       case WM_CREATE:
  480.       {
  481.          LPCREATESTRUCT lpCs = (LPCREATESTRUCT)lParam;
  482.          LPEWDATA lpEw;
  483.          int i, j;
  484.  
  485.          lpEw = (LPEWDATA)lpCs->lpCreateParams;
  486.          i = lstrlen( lpEw->szAuthorData );
  487.          if( ! i )
  488.          {
  489.             DestroyWindow( hWnd );
  490.             return( TRUE );
  491.          }
  492.  
  493.          for( j = 0; j < i; j++ )             //  Loop through string looking
  494.             if( lpEw->szAuthorData[ j ] == ':' ) //  for name/color separator
  495.                break;                                //  If found, break loop
  496.  
  497.          if( i != j )                         //  If title and color included
  498.          {
  499.             lpEw->szAuthorData[ j ] = '\0';            //  Separate with NULL
  500.             SetWindowText( hWnd, lpEw->szAuthorData );        //  Apply title
  501.  
  502.             i = 0;
  503.             if( lpEw->szAuthorData[ j + 1 ] == '1' )             //  Use RED?
  504.                i += 1;
  505.             if( lpEw->szAuthorData[ j + 2 ] == '1' )           //  Use GREEN?
  506.                i += 2;
  507.             if( lpEw->szAuthorData[ j + 3 ] == '1' )            //  Use BLUE?
  508.                i += 4;
  509.  
  510.             SetWindowLong( hWnd, RPOINTER_COLOR, i );
  511.          }
  512.          else
  513.          {
  514.             SetWindowText( hWnd, lpEw->szAuthorData );   //  No initial color
  515.             SetWindowWord( hWnd, RPOINTER_COLOR, 7 );    //  Default to white
  516.          }
  517.  
  518.          break;
  519.       }
  520.  
  521.       case WM_PAINT:
  522.       {
  523.          PAINTSTRUCT Ps;
  524.          HDC hDC;
  525.          HBRUSH hBrush;
  526.          int r, g, b, t;
  527.          POINT Pt[ 4 ];
  528.  
  529.          hDC = BeginPaint( hWnd, &Ps );
  530.          t = GetWindowLong( hWnd, RPOINTER_COLOR );        //  Get color bits
  531.  
  532.          r = g = b = 0;
  533.          if( t & 1 )
  534.             r = 255;
  535.          if( t & 2 )
  536.             g = 255;
  537.          if( t & 4 )
  538.             b = 255;
  539.  
  540.          hBrush = CreateSolidBrush( RGB( r, g, b ) );
  541.          SelectObject( hDC, hBrush );
  542.          SelectObject( hDC, GetStockObject( BLACK_PEN ) );
  543.  
  544.          Pt[ 0 ].x = 0;                            //  Initialize point array
  545.          Pt[ 0 ].y = 0;
  546.          Pt[ 1 ].x = 10;
  547.          Pt[ 1 ].y = 5;
  548.          Pt[ 2 ].x = 0;
  549.          Pt[ 2 ].y = 10;
  550.          Pt[ 3 ].x = 0;
  551.          Pt[ 3 ].y = 0;
  552.  
  553.          Polygon( hDC, (LPPOINT)Pt, 4 );               //  Draw right pointer
  554.  
  555.          EndPaint( hWnd, &Ps );
  556.          DeleteObject( hBrush );
  557.          return( TRUE );
  558.       }
  559.  
  560.       case WM_USER + 1024:
  561.       {
  562.          SetWindowLong( hWnd, RPOINTER_COLOR, wParam ); //  Color passed in wParam
  563.          InvalidateRect( hWnd, NULL, TRUE );        //  Redraw with new color
  564.          return( TRUE );
  565.       }
  566.  
  567.       default:
  568.          return( DefWindowProc( hWnd, msg, wParam, lParam ) );
  569.    }
  570.    return( FALSE );
  571. }
  572.  
  573.  
  574. /****************************************************************************
  575. *                                                                           *
  576. *             SetRightPointerColor() - Call as a Winhelp macro              *
  577. *                                                                           *
  578. ****************************************************************************/
  579.  
  580. BOOL CALLBACK SRPC( LPSTR lpWinHelp, LPSTR lpTitle, LPSTR lpColorBits )
  581. {
  582.     return( SetRightPointerColor( lpWinHelp, lpTitle, lpColorBits ) );
  583. }
  584.  
  585. BOOL CALLBACK SetRightPointerColor( LPSTR lpWinHelp, LPSTR lpTitle,
  586.                                     LPSTR lpColorBits )
  587. {
  588.    FINDWIN Fw;
  589.    HWND hWnd;
  590.  
  591.    if( ! lpTitle || ! lpColorBits || ! lpWinHelp )   //  If parameter is NULL
  592.       return( FALSE );                                           //  exit now
  593.  
  594.    if( ! lstrlen( lpTitle ) || lstrlen( lpColorBits ) < 3 )
  595.       return( FALSE );                            //  No invalid ones, either
  596.  
  597.    hWnd = FindWindow( NULL, lpWinHelp );              //  Find Winhelp window
  598.    if( ! hWnd )
  599.       return( FALSE );                            //  If can't be found, exit
  600.  
  601.    Fw.lpChildName = lpTitle;                //  Pass child title and color to
  602.    Fw.lpColorBits = lpColorBits;                //  enum proc using structure
  603.     Fw.Operation = 0;
  604.  
  605.    EnumChildWindows( hWnd, FindRPntProc, (LONG)(FINDWIN *)&Fw );
  606.  
  607.    return( TRUE );
  608. }
  609.  
  610.  
  611. /****************************************************************************
  612. *                                                                           *
  613. *       Used to find correct right pointer window to accept new color       *
  614. *                                                                           *
  615. ****************************************************************************/
  616.  
  617. BOOL CALLBACK FindRPntProc( HWND hWnd, LONG lParam )
  618. {
  619.    FINDWIN *lpFw = (FINDWIN *)lParam;
  620.    char str[ 30 ];
  621.    int t;
  622.  
  623.    if( ! hWnd )
  624.       return( FALSE );
  625.  
  626.    GetWindowText( hWnd, str, 30 );              //  Get title of child window
  627.    if( ! lstrcmpi( str, lpFw->lpChildName ) )  //  If this is the one we want
  628.    {
  629.       if( ! lpFw->Operation )
  630.       {
  631.          t = 0;
  632.          if( *lpFw->lpColorBits == '1' )
  633.             t += 1;
  634.          if( *( lpFw->lpColorBits + 1 ) == '1' )
  635.             t += 2;
  636.          if( *( lpFw->lpColorBits + 2 ) == '1' )
  637.             t += 4;
  638.                                                //  Change color via a message
  639.          PostMessage( hWnd, WM_USER + 1024, t, 0 );
  640.          return( FALSE );
  641.       }
  642.    }
  643.    return( TRUE );
  644. }
  645.  
  646.  
  647. /****************************************************************************
  648. *                                                                           *
  649. *         Center a secondary window with respect to the main window         *
  650. *                                                                           *
  651. ****************************************************************************/
  652.  
  653. BOOL CALLBACK CenterWindow( LPSTR lpWinHelp, LPSTR lpChild )
  654. {
  655.    HWND hHelp;
  656.    HWND hChild;
  657.    int x, y;
  658.    RECT pRect;
  659.    RECT cRect;
  660.  
  661.    if( ! lpWinHelp || ! lpChild )          //  If either pointer is bad, exit
  662.       return( FALSE );
  663.                                     //  If either string is zero length, exit
  664.    if( ! lstrlen( lpWinHelp ) || ! lstrlen( lpChild ) )
  665.       return( FALSE );
  666.  
  667.    hHelp = FindWindow( NULL, lpWinHelp );           //  Find main help window
  668.    if( ! hHelp )
  669.       return( FALSE );
  670.  
  671.    hChild = FindWindow( NULL, lpChild );            //  Find secondary window
  672.    if( ! hChild )
  673.       return( FALSE );
  674.  
  675.    GetWindowRect( hHelp, &pRect );         //  Get screen coordinates of main
  676.    GetClientRect( hChild, &cRect );          //  Get size of secondary window
  677.                                            //  Figure out where "centered" is
  678.    x = pRect.left + ( ( pRect.right - pRect.left - cRect.right ) >> 1 );
  679.    y = pRect.top + ( ( pRect.bottom - pRect.top - cRect.bottom ) >> 1 );
  680.  
  681.                                                //  Reposition window and exit
  682.    SetWindowPos( hChild, NULL, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE );
  683.    return( TRUE );
  684. }
  685.  
  686.  
  687. /****************************************************************************
  688. *                                                                           *
  689. *      Align secondary window to main window's right, center vertically     *
  690. *                                                                           *
  691. ****************************************************************************/
  692.  
  693. BOOL CALLBACK RightAlignWindow( LPSTR lpWinHelp, LPSTR lpChild )
  694. {
  695.    HWND hHelp;
  696.    HWND hChild;
  697.    int x, y;
  698.    RECT pRect;
  699.    RECT cRect;
  700.  
  701.    if( ! lpWinHelp || ! lpChild )          //  If either pointer is bad, exit
  702.       return( FALSE );
  703.                                     //  If either string is zero length, exit
  704.    if( ! lstrlen( lpWinHelp ) || ! lstrlen( lpChild ) )
  705.       return( FALSE );
  706.  
  707.    hHelp = FindWindow( NULL, lpWinHelp );        //  Find main window or exit
  708.    if( ! hHelp )
  709.       return( FALSE );
  710.  
  711.    hChild = FindWindow( NULL, lpChild );    //  Find secondary window or exit
  712.    if( ! hChild )
  713.       return( FALSE );
  714.  
  715.    GetWindowRect( hHelp, &pRect );         //  Get screen coordinates of main
  716.    GetClientRect( hChild, &cRect );          //  Get client size of secondary
  717.                                                    //  Right align secoondary
  718.    x = pRect.right - cRect.right - ( GetSystemMetrics( SM_CXFRAME ) << 1 ) - 4;
  719.    y = pRect.top + ( ( pRect.bottom - pRect.top - cRect.bottom ) >> 1 );
  720.  
  721.                                                       //  Reposition and exit
  722.    SetWindowPos( hChild, NULL, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE );
  723.    return( TRUE );
  724. }
  725.  
  726.